#include "UnitArbitrator.h"

#include "DefenseManager.h"
#include "ScoutManager.h"
#include "TaskExecutor.h"
#include "WorkerManager.h"
#include "..\Util.h"

namespace BroodWar
{
	namespace Addon
	{
		BWSAL::UnitController* ConvertUnitController(IUnitController^ controller)
		{
			DefenseManager^ defence = dynamic_cast<DefenseManager^>(controller);
			if(defence != nullptr)
				return (BWSAL::UnitController*)(defence->instance);
			ScoutManager^ scout = dynamic_cast<ScoutManager^>(controller);
			if(scout != nullptr)
				return (BWSAL::UnitController*)(scout->instance);
			TaskExecutor^ task = dynamic_cast<TaskExecutor^>(controller);
			if(task != nullptr)
				return (BWSAL::UnitController*)(task->instance);
			WorkerManager^ worker = dynamic_cast<WorkerManager^>(controller);
			if(worker != nullptr)
				return (BWSAL::UnitController*)(worker->instance);
			throw gcnew NotSupportedException("Inheritors are yet not supported");
		}

		UnitArbitrator::UnitArbitrator()
		{
			instance = new BWSAL::UnitArbitrator();
		}

		UnitArbitrator::~UnitArbitrator()
		{
			delete s_instance;
		}

		UnitArbitrator::!UnitArbitrator()
		{
			delete s_instance;
		}

		UnitArbitrator^ UnitArbitrator::Instance::get()
		{
			if(s_instance == nullptr)
				s_instance = gcnew UnitArbitrator();
			return s_instance;
		}

		bool UnitArbitrator::SetBid(IUnitController^ controller, Unit^ unit, double bid)
		{
			return instance->setBid(ConvertUnitController(controller), Api::ConvertUnit(unit), bid);
		}

		bool UnitArbitrator::SetBid(IUnitController^ controller, IEnumerable<Unit^>^ units, double bid)
		{
			return instance->setBid(ConvertUnitController(controller), ToSet<Unit^, BWAPI::Unit*>(units, &Api::ConvertUnit), bid);
		}
		
		bool UnitArbitrator::RemoveBid(IUnitController^ controller, Unit^ unit)
		{
			return instance->removeBid(ConvertUnitController(controller), Api::ConvertUnit(unit));
		}
		
		bool UnitArbitrator::RemoveBid(IUnitController^ controller, IEnumerable<Unit^>^ units)
		{
			return instance->removeBid(ConvertUnitController(controller), ToSet<Unit^, BWAPI::Unit*>(units, &Api::ConvertUnit));
		}
		
		bool UnitArbitrator::RemoveAllBids(IUnitController^ controller)
		{
			return instance->removeAllBids(ConvertUnitController(controller));
		}
		
		bool UnitArbitrator::RemoveController(IUnitController^ controller)
		{
			return instance->removeController(ConvertUnitController(controller));
		}
		
		bool UnitArbitrator::Accept(IUnitController^ controller, Unit^ unit, double bid)
		{
			return instance->accept(ConvertUnitController(controller), Api::ConvertUnit(unit), bid);
		}
		
		bool UnitArbitrator::Accept(IUnitController^ controller, IEnumerable<Unit^>^ units, double bid)
		{
			return instance->accept(ConvertUnitController(controller), ToSet<Unit^, BWAPI::Unit*>(units, &Api::ConvertUnit), bid);
		}
		
		bool UnitArbitrator::Accept(IUnitController^ controller, Unit^ unit)
		{
			return instance->accept(ConvertUnitController(controller), Api::ConvertUnit(unit));
		}
		
		bool UnitArbitrator::Accept(IUnitController^ controller, IEnumerable<Unit^>^ units)
		{
			return instance->accept(ConvertUnitController(controller), ToSet<Unit^, BWAPI::Unit*>(units, &Api::ConvertUnit));
		}
		
		bool UnitArbitrator::Decline(IUnitController^ controller, Unit^ unit, double bid)
		{
			return instance->decline(ConvertUnitController(controller), Api::ConvertUnit(unit), bid);
		}
		
		bool UnitArbitrator::Decline(IUnitController^ controller, IEnumerable<Unit^>^ units, double bid)
		{
			return instance->decline(ConvertUnitController(controller), ToSet<Unit^, BWAPI::Unit*>(units, &Api::ConvertUnit), bid);
		}

		bool UnitArbitrator::HasBid(Unit^ unit)
		{
			return instance->hasBid(ConvertUnit(unit));
		}
		
		//Tuple<IUnitController^, double>^ UnitArbitrator::GetHighestBidder(Unit^ unit)
		//{
		//}
		
		//List<Tuple<IUnitController^, double>^>^ UnitArbitrator::GetAllBidders(Unit^ unit)
		//{
		//}
		
		HashSet<Unit^>^ UnitArbitrator::GetObjects(IUnitController^ controller)
		{
			return ToHashSet<BWAPI::Unit*, Unit^>(instance->getObjects(ConvertUnitController(controller)), &Api::ConvertUnit);
		}
		
		HashSet<Unit^>^ UnitArbitrator::GetObjectsBidOn(IUnitController^ controller)
		{
			return ToHashSet<BWAPI::Unit*, Unit^>(instance->getObjectsBidOn(ConvertUnitController(controller)), &Api::ConvertUnit);
		}

		void UnitArbitrator::OnRemoveObject(Unit^ unit)
		{
			instance->onRemoveObject(ConvertUnit(unit));
		}
		
		//double UnitArbitrator::GetBid(IUnitController^ controller, Unit^ unit)
		//{
		//	return instance->getBid(ConvertUnitController(controller), ConvertUnit(unit));
		//}

		void UnitArbitrator::Update()
		{
			instance->update();
		}
	}
}
